home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dd / menu.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  27KB  |  922 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6. #include     "defs.h"
  7. #include    "dbug_protos.h"
  8.  
  9.  
  10. Prototype BOOL     enable_menus(void);
  11. Prototype void     init_default_menus(void);
  12. Prototype void     free_menus(void);
  13. Prototype void     set_menu_item(int num, int type, unsigned char *str, unsigned char *cmd, unsigned char *comkey);
  14. Prototype void     do_scroller(void);
  15. Prototype UWORD FindScrollerTop(UWORD total, UWORD displayable, UWORD pot);
  16. Prototype int     FindScrollerValues(UWORD total, UWORD displayable, UWORD top, WORD overlap, UWORD *body, UWORD *pot);
  17. Prototype void     setscrollbar(int flag);
  18. Prototype void     ActivateArrows(struct Window *win);
  19. Prototype void     InActivateArrows(struct Window *win);
  20. Prototype BOOL     ProcessMenuItem(char *args,int type);
  21. Prototype int    FindSlot(char *args);
  22.  
  23. #define MAXMENU         128     /* Maxumum number of user menus         */
  24. #define GADTOOLSBASE    GadToolsBase
  25.  
  26. struct Menu      *DebugMenu = NULL;
  27. struct NewMenu newmenu[MAXMENU];
  28. int MenuFlag = 0;
  29. unsigned long  ScrollStart = 0xffffffff;
  30. unsigned long  ScrollEnd = 0;
  31. int SymbolCount;
  32.  
  33. struct InitMenu {
  34.     int type;
  35.     int num;
  36.     unsigned char *str;
  37.     unsigned char *cmd;
  38.     unsigned char *comkey;
  39. };
  40.  
  41. #define NM_BAR    4
  42.  
  43. struct InitMenu IMenu[] = {
  44.  NM_TITLE,     1, "Project",         "",NULL,
  45.  NM_ITEM,     1, "New",         "reset",NULL,
  46.  NM_BAR,    1, "",            "",NULL,
  47.  NM_ITEM,     1, "Open",         "open",NULL,
  48.  NM_SUB,     1, "Source",         "open source",NULL,
  49.  NM_SUB,     1, "Mixed",         "open mixed",NULL,
  50.  NM_SUB,     1, "Dism",         "open dism",NULL,
  51.  NM_SUB,     1, "Bytes",         "open bytes",NULL,
  52.  NM_SUB,     1, "Symbols",         "open symbols",NULL,
  53.  NM_SUB,     1, "Sorted symbols",     "open symlist",NULL,
  54.  NM_SUB,     1, "Breakpoints",    "open breakpoints",NULL,
  55.  NM_ITEM,     1, "Close",         "close","C",
  56.  NM_BAR,    1, "",            "",NULL,
  57.  NM_ITEM,     1, "Save Prefs",     "saveprefs",NULL,
  58.  NM_BAR,    1, "",            "",NULL,
  59.  
  60.  NM_ITEM,     1, "Quit",         "quit","Q",
  61.  
  62.  NM_TITLE,    2, "Display",        "",NULL,
  63.  NM_ITEM,    2, "Source",         "source","S",
  64.  NM_ITEM,    2, "Mixed",         "mixed","M",
  65.  NM_ITEM,    2, "Dism",         "dism","D",
  66.  NM_ITEM,    2, "Bytes",         "bytes","B",
  67.  NM_ITEM,    2, "Words",         "words","W",
  68.  NM_ITEM,    2, "Longs",         "longs","L",
  69.  NM_ITEM,    2, "Registers",     "registers","R",
  70.  NM_ITEM,    2, "Offsets",         "offsets",NULL,
  71.  
  72.  NM_TITLE,    3, "Program Info",    "",NULL,
  73.  NM_ITEM,    3, "Info on task",     "info",NULL,
  74.  NM_ITEM,    3, "Hunks",         "hunks",NULL,
  75.  NM_ITEM,    3, "Symbols",         "symbols",NULL,
  76.  NM_ITEM,    3, "Sorted symbols",     "symlist",NULL,
  77.  
  78.  NM_TITLE,    4, "System Info",    "",NULL,
  79.  NM_ITEM,    14, "Tasks",         "tasks","",
  80.  NM_ITEM,    15, "Libraries",     "libs","",
  81.  NM_ITEM,    15, "Devices",         "devices","",
  82.  NM_ITEM,    16, "ExecBase",         "execbase","",
  83.  NM_ITEM,    18, "DosBase",         "dosbase",NULL,
  84.  NM_ITEM,    19, "Memory",        "memlist",NULL,
  85.  NM_ITEM,    19, "Interrupts",    "intrs",NULL,
  86.  NM_ITEM,    19, "Ports",        "ports",NULL,
  87.  NM_ITEM,    19, "Resource",        "resources",NULL,
  88.  NM_ITEM,    11, "Process",         "process",NULL,
  89.  
  90.  NM_TITLE,    13, "Breakpoints",    "",NULL,
  91.  NM_ITEM,    19, "Breakpoints",    "breakpoints",NULL,
  92.  NM_ITEM,    19, "Clear Breakpoint",    "clear",NULL,
  93.  NM_ITEM,    19, "Clear All",    "clear all",NULL,
  94.  NM_ITEM,    19, "Set Breakpoint",    "bp",NULL,
  95.  
  96.  NM_TITLE,    13, "Watchpoints",    "",NULL,
  97.  NM_ITEM,    22, "Watch Byte",     "watchbyte",NULL,
  98.  NM_ITEM,    22, "Watch Word",     "watchword",NULL,
  99.  NM_ITEM,    22, "Watch Long",     "watchlong",NULL,
  100.  
  101.  NM_TITLE,    21, "Misc",        "",NULL,
  102.  NM_ITEM,    22, "Help",         "help",NULL,
  103.  NM_ITEM,    22, "REXX Command",     "rexx",NULL,
  104.  NM_ITEM,    22, "Alias",         "alias",NULL,
  105.  NM_ITEM,    22, "Unalias",         "unalias",NULL,
  106.  NM_ITEM,    22, "Fkey",         "fkey",NULL,
  107.  NM_ITEM,    22, "Set",         "set",NULL,
  108.  NM_END,    23, ""  , "", NULL
  109. };
  110.  
  111.  
  112. // Initialize default DD menus
  113.  
  114. void init_default_menus(void)
  115. {
  116. int i;
  117.  
  118.     if(!MenuFlag) {  // default menus not set
  119.         MenuFlag = TRUE;
  120.         memset((char *)newmenu,NM_END,sizeof(newmenu));
  121.         for(i=0; i< MAXMENU; i++) {
  122.             set_menu_item(i,IMenu[i].type,IMenu[i].str,IMenu[i].cmd,IMenu[i].comkey);
  123.             if(IMenu[i].type == NM_END)return;
  124.     }
  125.     }
  126. }
  127.  
  128.  
  129. // handle argument parsing for setting a menu item
  130. BOOL ProcessMenuItem(char *args,int type)
  131. {
  132. char *ptr, *string, *dp;
  133. char xname[3][80];
  134. int n, i = 0, quote = 1, flag = TRUE, iflag;
  135.  
  136.     memset(xname[1],0,80);    /* zero the optionals */
  137.     memset(xname[2],0,80);
  138.  
  139.  
  140.     if(string = strchr(args,' ')) {    // slot first, no sense in continuing without that
  141.         *string++ = NULL;
  142.         if((n = FindSlot(args)) < 0)return FALSE;    // no slot available
  143.         string = SkipBlanks(string);
  144.         ptr = string;
  145.         while (flag && (i < 3)) {
  146.         iflag = 1;
  147.         dp = xname[i++];
  148.         while(*ptr && iflag) {
  149.             switch((int) *ptr) {
  150.                 case '\"':
  151.                 quote *= -1;
  152.                 break;
  153.                 case '\t':
  154.                 case ' ':
  155.                 if(quote > 0) {
  156.                 iflag = 0;  // not in quotes
  157.                 break;
  158.             }
  159.                 // fall through
  160.                 default:
  161.                 *dp++ = *ptr; //++;
  162.         }
  163.             ptr++;
  164.         }
  165.         *dp = NULL;        // terminate the string
  166.             if(! *ptr)flag = FALSE;    // done with args
  167.     }
  168.         if(i) {
  169.         set_menu_item(n, type, xname[0], xname[1], xname[2]);
  170.             return(TRUE);
  171.     }
  172.     }
  173. return FALSE;
  174. }
  175.  
  176.  
  177.  
  178. int FindSlot(char *args)
  179. {
  180. int n;
  181.  
  182.     if((n = strtol(args,NULL,10)) >= 0 && (n < MAXMENU))return n;    // normal slot specified
  183.     if(n == -1) { // its an append operation
  184.         for(n=0; n < (MAXMENU-1); n++)if(newmenu[n].nm_Type == NM_END) {
  185.         set_menu_item(n+1,NM_END,"","","");  // add the new end marker
  186.         return n;
  187.     }
  188.     }
  189.     ScrStatus("*** Error: can't find position");
  190.     return -1;
  191. }
  192.  
  193. // enable current set of menus
  194. BOOL enable_menus(void)
  195. {
  196.     DBugDisp *disp;
  197.     BOOL flag = FALSE;
  198.     struct VisualInfo *vi;   
  199.     struct TagItem taglist[3] = {
  200.     {GTMN_FrontPen, NULL},
  201.     {GTMN_FullMenu, TRUE},
  202.     {TAG_DONE, NULL}
  203.     };
  204.  
  205.    // clear all menus from active windows on display list
  206.    for (disp = (DBugDisp *)DisplayList.lh_Head; disp->ds_Node.ln_Succ; disp = (DBugDisp *)disp->ds_Node.ln_Succ) {
  207.     if(disp->ds_Win)ClearMenuStrip(disp->ds_Win);
  208.    }
  209.  
  210.  
  211.    if(GADTOOLSBASE) {
  212.        if (DebugMenu != NULL) {
  213.         FreeMenus(DebugMenu);
  214.                DebugMenu = NULL;
  215.        }
  216.  
  217.        if (!(DebugMenu = CreateMenusA(newmenu, taglist)))return 0;
  218.  
  219.        if ((vi = GetVisualInfoA((CurDisplay->ds_Win)->WScreen, taglist+1))) {
  220.             if (!LayoutMenusA(DebugMenu, vi, taglist+1)) {
  221.                 FreeVisualInfo(vi);
  222.             return 0;
  223.         }
  224.        }
  225.        FreeVisualInfo(vi);
  226.    }
  227.    else {    // gadtools unavailable, so lets do it ourself
  228.         if (DebugMenu != NULL) {
  229.         v_free_menus(DebugMenu);
  230.                DebugMenu = NULL;
  231.         }
  232.         if(!(DebugMenu = v_create_menus(newmenu)))return 0;
  233.     if(!v_layout_menus(DebugMenu))return 0;
  234.    }
  235.  
  236.    // Set the menu strips for active windows
  237.    for (disp = (DBugDisp *)DisplayList.lh_Head; disp->ds_Node.ln_Succ; disp = (DBugDisp *)disp->ds_Node.ln_Succ) {
  238.     if(disp->ds_Win)SetMenuStrip(disp->ds_Win, DebugMenu);
  239.    }
  240.    // and for current window (possibly not on display list yet)
  241.    if(CurDisplay && CurDisplay->ds_Win)
  242.        flag = (BOOL)SetMenuStrip(CurDisplay->ds_Win, DebugMenu); 
  243.    return flag;
  244. }
  245.  
  246.  
  247.  
  248. /***
  249. *
  250. * Set up a menu item to a given string and command
  251. *
  252. ***/
  253. void set_menu_item(int num, int type, unsigned char *str, unsigned char *cmd,
  254.     unsigned char *comkey)
  255. {
  256.    DBugDisp *disp;
  257.  
  258.    if (num < 0 || num >= MAXMENU) {
  259.     return;
  260.    }
  261.    // shutdown all menu items from active windows until they next do an enable
  262.    for (disp = (DBugDisp *)DisplayList.lh_Head; disp->ds_Node.ln_Succ; disp = (DBugDisp *)disp->ds_Node.ln_Succ) {
  263.     if(disp->ds_Win)ClearMenuStrip(disp->ds_Win);
  264.    }
  265.  
  266.    /* First we free up any menu item that might be there */
  267.    if (newmenu[num].nm_UserData != NULL) {
  268.     free(newmenu[num].nm_UserData);
  269.     newmenu[num].nm_UserData = NULL;
  270.    }
  271.    if ((newmenu[num].nm_Label != NULL) && (newmenu[num].nm_Label != NM_BARLABEL)) {
  272.       free(newmenu[num].nm_Label);
  273.       newmenu[num].nm_Label = NULL;
  274.    }
  275.  
  276.    if (newmenu[num].nm_CommKey != NULL) {
  277.       free(newmenu[num].nm_CommKey);
  278.       newmenu[num].nm_CommKey = NULL;
  279.    }
  280.    newmenu[num].nm_UserData=(void *)malloc(strlen(cmd)+8);
  281.    newmenu[num].nm_Label= (type == 4) ? NM_BARLABEL: malloc(strlen(str)+8);
  282.  
  283.    if(comkey && *comkey) {
  284.         newmenu[num].nm_CommKey=(void *)malloc(strlen(comkey)+8);
  285.    }
  286.  
  287.    if((newmenu[num].nm_UserData == NULL)|| (newmenu[num].nm_Label==NULL) ||
  288.    ((comkey && *comkey) && (newmenu[num].nm_CommKey == NULL))) {
  289.       newmenu[num].nm_Type = 0;
  290.       return;    /* out of memory */
  291.    }
  292.  
  293.    strcpy(((char *)newmenu[num].nm_UserData), cmd);
  294.  
  295.    if (type == 4) type = 2;
  296.    else strcpy(newmenu[num].nm_Label,str);
  297.  
  298.    newmenu[num].nm_Type = type;
  299.    newmenu[num].nm_Flags = 0;
  300.  
  301.    if(comkey && *comkey)strcpy(((char *)newmenu[num].nm_CommKey), comkey);
  302.    else newmenu[num].nm_CommKey = 0;
  303. }
  304.  
  305. /* Free up all menu storage */
  306. void free_menus(void)
  307. {
  308.    int i;
  309.  
  310.    if (DebugMenu != NULL) {
  311.       if(GADTOOLSBASE)FreeMenus(DebugMenu);
  312.       else v_free_menus(DebugMenu);
  313.       DebugMenu = NULL;
  314.    }
  315.  
  316.    for (i = 0; i < MAXMENU; i++) {
  317.       if (newmenu[i].nm_UserData != NULL)free(newmenu[i].nm_UserData);
  318.       if ((newmenu[i].nm_Label != NULL) && (newmenu[i].nm_Label != NM_BARLABEL))free(newmenu[i].nm_Label);
  319.       if (newmenu[i].nm_CommKey != NULL)free(newmenu[i].nm_CommKey);
  320.  
  321.       newmenu[i].nm_UserData = NULL;
  322.       newmenu[i].nm_Label    = NULL;
  323.       newmenu[i].nm_CommKey  = NULL;
  324.    }
  325. }
  326.  
  327.  
  328. extern struct Gadget ColorGadget;
  329. extern struct Gadget DownGadget;
  330. extern struct Gadget UpGadget;
  331. extern struct Image ColorPropImage;
  332. extern struct PropInfo ColorPropInfo;
  333.  
  334.  
  335. /* Set size of scroll bar.  If flag is true, remove the scroll bar first */
  336.  
  337. void setscrollbar(int flag)
  338. {
  339.     WINDOW *win;
  340.  
  341.     if(CurDisplay) {
  342.     if((win = CurDisplay->ds_Win)) {
  343.             if(flag)RemoveGadget(win,&ColorGadget);
  344.             else {    /* first time through */
  345.         AddGadget(win,&UpGadget,(UWORD)~0);
  346.             AddGadget(win,&DownGadget,(UWORD)~0);
  347.         }
  348.     }
  349.     }
  350.  
  351.     /* Set up the scroll bar */
  352.     ColorGadget.LeftEdge = - win->BorderRight + 4;
  353.     ColorGadget.TopEdge = win->BorderTop;
  354.     ColorGadget.Height=win->Height - win->BorderBottom - win->BorderTop-8 - 22;
  355.     ColorGadget.Width= 14; /* win->BorderRight-3; */
  356.     ColorPropInfo.VertBody = 0xFFFF;    /* starts with nothing */
  357.  
  358.     AddGadget(win,&ColorGadget,(UWORD)~0);
  359.     RefreshGadgets(&UpGadget,win,NULL);    /* refresh just the scroll bar */
  360. }
  361.  
  362. int FindScrollerValues(UWORD total, UWORD displayable, UWORD top,
  363.            WORD overlap, UWORD *body, UWORD *pot)
  364. {
  365. // UWORD hidden;
  366. int hidden;
  367. UWORD oldbody = *body;
  368. UWORD oldpot = *pot;
  369. int temp1 = total, temp2 = displayable;
  370.  
  371. hidden = MAX(temp1-temp2, 0);
  372.  
  373. if(top > hidden)top = hidden;
  374.  
  375. (*body) = (hidden > 0) ? (UWORD)(((ULONG)(displayable - overlap)*MAXBODY)
  376.         / (total - overlap)) : MAXBODY;
  377.  
  378. (*pot) = (hidden > 0) ? (UWORD) (((ULONG)top * MAXPOT)/hidden) : 0;
  379.  
  380. if((oldbody == *body) && (oldpot == *pot))return(FALSE);
  381. return(TRUE);
  382. }
  383.  
  384.  
  385. UWORD FindScrollerTop(UWORD total, UWORD displayable, UWORD pot)
  386. {
  387. //UWORD top, hidden;
  388. int top, hidden;
  389. int temp1 = total, temp2 = displayable;
  390.  
  391. hidden = MAX(temp1-temp2, 0);
  392. top = ((((ULONG) hidden * pot) + (MAXPOT/2)) >> 16); /* range from 0 to ... */
  393.  
  394. return(top);
  395. }
  396.  
  397.  
  398. void do_scroller(void)
  399. {
  400. WINDOW *win;
  401. ULONG total, top;
  402. int rows;
  403.  
  404.     if(CurDisplay) {
  405.     if((win = CurDisplay->ds_Win)) {
  406.     rows = CurDisplay->ds_ScrRows;
  407.             // calc new values
  408.  
  409.         top = CurDisplay->ds_WindowTop;  // current top for almost all display modes
  410.  
  411.         switch(CurDisplay->ds_DisplayMode) {
  412.         case DISPLAY_DISM:
  413.         case DISPLAY_SOURCE:
  414.         case DISPLAY_MIXED:
  415.         case DISPLAY_BYTES:
  416.         case DISPLAY_WORDS:
  417.         case DISPLAY_LONGS:
  418.  
  419.             total = (ScrollEnd - ScrollStart) >> 5;
  420.             top = ((int)CurDisplay->ds_WindowTop - (int)ScrollStart) >> 5;
  421.  
  422.             if((int)top < 0 ) top = 0;
  423.             break;
  424.  
  425.         case DISPLAY_SYMBOL:
  426.             total = SymbolCount;
  427.             break;
  428.  
  429.         case DISPLAY_HUNKS:
  430.             total = numHunks;
  431.             break;
  432.  
  433.         case DISPLAY_HELP:
  434.             total = HelpSize();
  435.             break;
  436.  
  437.         case DISPLAY_BREAK:
  438.             total = MAXBP+5;
  439.             top = topBP;
  440.             break;
  441.  
  442.         default:
  443.             total = SizeDLIST(&CurDisplay->ds_List);
  444.         }
  445.             if(FindScrollerValues(total, CurDisplay->ds_ScrRows, top, 2, 
  446.             &ColorPropInfo.VertBody,&ColorPropInfo.VertPot)) {
  447.         /* values changed, update */
  448.             NewModifyProp(&ColorGadget,win,NULL,PROPNEWLOOK | AUTOKNOB | FREEVERT,0, 
  449.             ColorPropInfo.VertPot,  0, ColorPropInfo.VertBody, -1 );
  450.         }
  451.     }
  452.     }
  453. }
  454.  
  455.  
  456. __chip const UWORD upPicture[] =
  457. {
  458. /* Plane 0 */
  459.     0x0000,0x0000,0x0000,0x0000,0x0180,0x0660,0x1818,0x0000,
  460.     0x0000,0x0000,0xFFFF,
  461. /* Plane 1 */
  462.     0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  463.     0x0000,0x0000,0x0000,
  464. };
  465.  
  466. __chip const UWORD upPictureSelect[] =
  467. {
  468. /* Plane 0 */
  469.     0x0000,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
  470.     0xFFFF,0xFFFF,0xFFFF,
  471. /* Plane 1 */
  472.     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFE7F,0xF99F,0xE7E7,0xFFFF,
  473.     0xFFFF,0xFFFF,0x0000,
  474. };
  475.  
  476. __chip const UWORD downPicture[] =
  477. {
  478. /* Plane 0 */
  479.     0x0000,0x0000,0x0000,0x0000,0x1818,0x0660,0x0180,0x0000,
  480.     0x0000,0x0000,0xFFFF,
  481. /* Plane 1 */
  482.     0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  483.     0x0000,0x0000,0x0000,
  484. };
  485.  
  486. __chip const UWORD downPictureSelect[] =
  487. {
  488. /* Plane 0 */
  489.     0x0000,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
  490.     0xFFFF,0xFFFF,0xFFFF,
  491. /* Plane 1 */
  492.     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xE7E7,0xF99F,0xFE7F,0xFFFF,
  493.     0xFFFF,0xFFFF,0x0000,
  494. };
  495.  
  496. struct Image UpImage =  {
  497.     -1, 0,              /* Left, Top */
  498.     16, 11, 2,        /* width, depth, height */
  499.     upPicture,
  500.     3, 0,                /* PlanePick, PlaneOnOff */
  501.     NULL
  502. };
  503.  
  504. struct Image DownImage = {
  505.     -1, 0,              /* Left, Top */
  506.     16, 11, 2,        /* width, height, depth */
  507.     downPicture,
  508.     3, 0,                /* PlanePick, PlaneOnOff */
  509.     NULL
  510. };
  511.  
  512. struct Image UpImageSelect =  {
  513.     -1, 0,              /* Left, Top */
  514.     16, 11, 2,        /* width, depth, height */
  515.     upPictureSelect,
  516.     3, 0,                /* PlanePick, PlaneOnOff */
  517.     NULL
  518. };
  519.  
  520. struct Image DownImageSelect = {
  521.     -1, 0,              /* Left, Top */
  522.     16, 11, 2,        /* width, height, depth */
  523.     downPictureSelect,
  524.     3, 0,                /* PlanePick, PlaneOnOff */
  525.     NULL
  526. };
  527.  
  528. struct Gadget UpGadget = {
  529.         NULL,        /* NextGadget */
  530.         -15, -31,          /* gadget hit box LeftEdge, TopEdge */
  531.         16, 11,          /* gadget hit box Width, Height */
  532.         GADGHCOMP|GADGIMAGE|GRELRIGHT|GRELBOTTOM|RIGHTBORDER, /* Flags */
  533.         RELVERIFY|GACT_IMMEDIATE,      /* Activation */
  534.         BOOLGADGET,     /* GadgetType */
  535.         &UpImageSelect,    /* GadgetRender */
  536.         NULL,           /* no SelectRender */
  537.         NULL,           /* no text for this gadget */
  538.         NULL,           /* no MutualExclude */
  539.         NULL,           /* no SpecialInfo */
  540.         ID_UP,              /* gadget ID */
  541.         NULL           /* no general purpose data */
  542. };
  543.  
  544. struct Gadget DownGadget = {
  545.     NULL,        /* NextGadget */
  546.         -15, -20,       /* gadget hit box LeftEdge, TopEdge */
  547.         16, 11,          /* gadget hit box Width, Height */
  548.         GADGHCOMP|GADGIMAGE|GRELRIGHT|GRELBOTTOM|RIGHTBORDER, /* Flags */
  549.         RELVERIFY|GACT_IMMEDIATE,      /* Activation */
  550.         BOOLGADGET,     /* GadgetType */
  551.         &DownImageSelect,       /* GadgetRender */
  552.         NULL,           /* no SelectRender */
  553.         NULL,           /* no text for this gadget */
  554.         NULL,           /* no MutualExclude */
  555.         NULL,           /* no SpecialInfo */
  556.         ID_DOWN,    /* gadget ID */
  557.         NULL           /* no general purpose data */
  558. }; 
  559.  
  560.  
  561. /* scroller gadgets */
  562.  
  563. #define COLOR_KNOB_BODY        0x1111
  564.  
  565. struct Image ColorPropImage;
  566.  
  567. struct PropInfo ColorPropInfo = {
  568.     PROPNEWLOOK | AUTOKNOB | FREEVERT,        /* flags */
  569.     0,                /* horiz pot */
  570.     0xFFFF,                /* vert pot */
  571.     0,                /* horiz body */
  572.     0,                /* vert body */
  573.     0, 0,                /* cwidth, cheight */
  574.     0, 0,                 /* HpotRes, VPotRes */
  575.     0, 0                /* Left border, Top border */
  576. };
  577.  
  578. struct Gadget ColorGadget = {
  579.     NULL,            /* Next gadget */
  580.     -10,            /* leftedge */
  581.     4,             /* top edge */
  582.     10,            /* width */
  583.     80,            /* height */
  584.     GADGHCOMP|GADGIMAGE|GRELRIGHT|RIGHTBORDER,    /* flags */
  585.     FOLLOWMOUSE|GACT_IMMEDIATE,    /* activation */
  586.     PROPGADGET,        /* gadget type */
  587.     &ColorPropImage,    /* gadget render */
  588.     NULL,            /* select render */
  589.     NULL,            /* gadget text */
  590.     NULL,            /* custom gadget hook */
  591.     &ColorPropInfo,        /* special info */
  592.     ID_SCROLL,        /* gadget ID */
  593.     NULL            /* user data */
  594. };
  595.  
  596. void ActivateArrows(struct Window *win)
  597. {
  598. int pos;
  599.  
  600.     pos = RemoveGadget(win,&UpGadget);
  601.     UpGadget.GadgetRender = &UpImageSelect;
  602.     AddGadget(win,&UpGadget,pos);
  603.  
  604.     pos = RemoveGadget(win,&DownGadget);
  605.     DownGadget.GadgetRender = &DownImageSelect;
  606.     AddGadget(win,&DownGadget,pos);
  607.  
  608. // refresh gadgets in do_scroller
  609.  
  610.     setscrollbar(1);
  611.     do_scroller();
  612. }
  613.  
  614. void InActivateArrows(struct Window *win)
  615. {
  616. int pos;
  617.  
  618.     pos = RemoveGadget(win,&UpGadget);
  619.     UpGadget.GadgetRender = &UpImage;
  620.     AddGadget(win,&UpGadget,pos);
  621.  
  622.     pos = RemoveGadget(win,&DownGadget);
  623.     DownGadget.GadgetRender = &DownImage;
  624.     AddGadget(win,&DownGadget,pos);
  625.  
  626.     RefreshGadgets(&UpGadget,win,NULL);    /* refresh just the scroll bar */
  627. }
  628.  
  629. Prototype struct Menu *v_create_menus(struct NewMenu *menulist);
  630. Prototype int v_layout_menus(struct Menu *menus);
  631. Prototype void v_free_menus(struct Menu *menus);
  632. Prototype int text_width(char *str);
  633. Local void *malloc_clear(ULONG bytes);
  634.  
  635. struct TextAttr TOPAZ80={"topaz.font",8,0,FPF_ROMFONT};
  636.  
  637. void *malloc_clear(ULONG bytes) {
  638. void *ptr = malloc(bytes);
  639.  
  640. if(ptr)memset(ptr,0,bytes);
  641.  
  642. return ptr;
  643. }
  644.  
  645. struct XMenu {
  646.    struct Menu      menu;
  647.    APTR             userdata;
  648.    struct Image     image;
  649. };
  650.  
  651. struct XItem {
  652.    struct MenuItem  item;
  653.    APTR             userdata;
  654.    struct IntuiText itext;
  655. };
  656.  
  657.  
  658. #define VBAR            2         /* Pixel width of a vertical BAR        */
  659. #define DVBAR           (2*VBAR)  /* Pixel width of two vertical BARs     */
  660. #define HBAR            1         /* Pixel height of a horizontal BAR     */
  661. #define DHBAR           (2*HBAR)  /* Pixel height of two Horizontal BARs  */
  662.  
  663. /***********************************************************************************
  664.  * Procedure: create_menus
  665.  * Synopsis:  Menu = create_menus(NewMenu);
  666.  * Purpose:   Create the appropriate menu structures for a given NewMenu list
  667.  ***********************************************************************************/
  668.  
  669. struct Menu *v_create_menus(struct NewMenu *menulist)
  670. {
  671.    int i;
  672.    struct Menu   *retmenu;
  673.    struct XMenu  *thismenu;
  674.    struct XItem  *thisitem;
  675.    static struct Image sep_image = {5, 1, 1000, 2,0, NULL, 0,0, NULL};
  676.  
  677.    /* We don't have GadTools around to do the work for us, so just create the */
  678.    /* Menu structures directly.                                               */
  679.  
  680.    retmenu = NULL;  /* Default to giving them NOTHING */
  681.    for (i = 0; i < MAXMENU; i++) {
  682.       switch (menulist[i].nm_Type) {
  683.          case NM_TITLE:
  684.             {
  685.                struct XMenu  *newmenu;
  686.  
  687.                newmenu = (struct XMenu *)malloc_clear(sizeof(struct XMenu));
  688.                if (newmenu == NULL) {
  689.                   v_free_menus(retmenu);
  690.                   return(NULL);
  691.                }
  692.  
  693.                /* Link the menu structure onto the list of other menus */
  694.                if (retmenu == NULL)retmenu = &newmenu->menu;
  695.                else thismenu->menu.NextMenu = &newmenu->menu;
  696.  
  697.                thismenu = newmenu;
  698.             }
  699.  
  700.             thismenu->menu.Flags    = MENUENABLED;
  701.             thismenu->menu.MenuName = menulist[i].nm_Label;
  702.             thismenu->userdata      = menulist[i].nm_UserData;
  703.             thismenu->image         = sep_image;
  704.             break;
  705.  
  706.         case NM_ITEM:
  707.         case NM_SUB:
  708.             if (thismenu == NULL) return(NULL);
  709.             {
  710.                struct XItem  *newitem;
  711.  
  712.                newitem = (struct XItem *)malloc_clear(sizeof(struct XItem));
  713.                if (newitem == NULL) {
  714.                   v_free_menus(retmenu);
  715.                   return(NULL);
  716.                }
  717.                if (thismenu->menu.FirstItem == NULL)
  718.             thismenu->menu.FirstItem = &newitem->item;
  719.                else {
  720.             for(thisitem = (struct XItem *)thismenu->menu.FirstItem; thisitem->item.NextItem; thisitem = (struct XItem *)thisitem->item.NextItem)
  721.             ;
  722.                     thisitem->item.NextItem  = &newitem->item;
  723.            }
  724.            thisitem = newitem;
  725.         }
  726.  
  727.             if (menulist[i].nm_Label == NM_BARLABEL) {
  728.                thisitem->item.Flags        = 0;
  729.                thisitem->item.ItemFill     = &thismenu->image;
  730.             }
  731.             else {
  732.                /* fill in the intuitext with some reasonable defaults */
  733.                thisitem->itext.FrontPen    = 0;
  734.                thisitem->itext.DrawMode    = JAM1;
  735.                thisitem->itext.LeftEdge    = 5;
  736.                thisitem->itext.TopEdge     = 1;
  737.                thisitem->itext.ITextFont   = &TOPAZ80;
  738.  
  739.  
  740.                thisitem->itext.IText       = menulist[i].nm_Label;
  741.  
  742.                thisitem->item.Flags        = ITEMTEXT|ITEMENABLED|HIGHCOMP;
  743.                thisitem->item.ItemFill     = (APTR)&thisitem->itext;
  744.                if (menulist[i].nm_CommKey) {
  745.                   thisitem->item.Command   = *menulist[i].nm_CommKey;
  746.                   thisitem->item.Flags    |= COMMSEQ;
  747.                }
  748.         }
  749.             thisitem->userdata = menulist[i].nm_UserData;
  750.             break;
  751.  
  752.          case NM_END:
  753.              return(retmenu);
  754.       }
  755.    }
  756.    return(retmenu);
  757. }
  758.  
  759. /***********************************************************************************
  760.  * Procedure: layout_menus
  761.  * Synopsis:  rc = layout_menus(Menu);
  762.  * Purpose:   Lays out a menu given the current global information
  763.  ***********************************************************************************/
  764. int v_layout_menus(struct Menu *menus)
  765. {
  766.    struct XMenu     *menu;
  767.    struct XItem     *item;
  768.    int              xpos;
  769.    int swidth, sheight, stxheight;
  770.  
  771.    xpos = VBAR;
  772.  
  773.    // get screen width and height for later
  774.  
  775.    if(CurDisplay && CurDisplay->ds_Win) {
  776.     swidth = CurDisplay->ds_Win->WScreen->Width;
  777.     sheight = CurDisplay->ds_Win->WScreen->Height;
  778.     stxheight = CurDisplay->ds_Win->RPort->TxHeight;
  779.    }
  780.    else {
  781.     swidth = 640;
  782.     sheight = 200;
  783.     stxheight = 8;
  784.    }
  785.    for (menu = (struct XMenu *)menus; menu; menu = (struct XMenu *)menu->menu.NextMenu) {
  786.       int width, ypos;
  787.  
  788.       /* set the x position of the menu to the next available position.
  789.        * Set the menu width based on the size of the text.
  790.        */
  791.  
  792.       menu->menu.LeftEdge = xpos;
  793.       menu->menu.Width    = text_width(menu->menu.MenuName) + DVBAR;
  794.  
  795.       /* set the initial item y-position to just below the title bar */
  796.  
  797.       ypos = 0;
  798.  
  799.       /* walk through the list of items for the first pass. The object
  800.        * is to find the width of the largest item. We will also set
  801.        * the y-position of each item on this pass.
  802.        */
  803.  
  804.       width = menu->menu.Width;    /* make items at least as big as menu */
  805.       for (item = (struct XItem *)menu->menu.FirstItem; item; item = (struct XItem *)item->item.NextItem) {
  806.          int  iwidth = 0;
  807.  
  808.          /* set the y-position of the item to the next available. Also,
  809.           * put the item just to the left of the menu. You can make
  810.           * this number zero if you prefer.
  811.           */
  812.  
  813.          item->item.TopEdge = ypos;
  814.          item->item.LeftEdge = -VBAR;
  815.  
  816.          /* if it's a text item, see how big it is. */
  817.  
  818.          if (item->item.Flags & ITEMTEXT) {
  819.             struct IntuiText *itext;
  820.  
  821.             itext = (struct IntuiText *)item->item.ItemFill;
  822.  
  823.             /* the height is just the font height + 2. The width is
  824.              * based on the string pixel width.
  825.              */
  826.             item->item.Height = 2 + stxheight;
  827.             iwidth = text_width(itext->IText) + 10;
  828.             /* if it has a command-key sequence, then add in the space needed
  829.              * for the command key and the command symbol. Note that in
  830.              * lo-res, we should actually use LOWCOMMWIDTH, but I'm
  831.              * feeling lazy today.
  832.              */
  833.  
  834.             if (item->item.Flags & COMMSEQ) {
  835.                char buf[2];
  836.  
  837.                buf[0] = item->item.Command;
  838.                buf[1] = 0;
  839.                iwidth += text_width(buf) + COMMWIDTH + 8;
  840.             }
  841.      }
  842.          else {
  843.             /* separator bars are always the same height */
  844.             item->item.Height = 4;
  845.          }
  846.  
  847.          /* update the y-position variable. Make sure the items don't
  848.           * run off the bottom.
  849.           */
  850.  
  851.          ypos  += item->item.Height;
  852.      if (ypos >= (sheight - DHBAR))return 0;
  853.  
  854.           /* now see if this item is the largest one. */
  855.           if (iwidth > width) width = iwidth;
  856.       }
  857.  
  858.       /* on our second pass, we set the widths of all the items to the
  859.        * width of the largest item so that it looks good. In addition,
  860.        * we are going to adjust menus that might run off the right edge.
  861.        */
  862.  
  863.       for (item = (struct XItem *)menu->menu.FirstItem; item; item = (struct XItem *)item->item.NextItem) {
  864.          item->item.Width = width;
  865.          if ((xpos + width) >= (swidth - 2))item->item.LeftEdge = swidth - 2 - xpos - width;
  866.       }
  867.  
  868.       menu->image.Width = width - 7;
  869.  
  870.       /* now update the x position variable, make sure that the menu
  871.        * header is not off the edge of the screen, and add a little space
  872.        * between the headers. Feel free to make this number whatever
  873.        * you want. If you are feeling really ambitious, you could
  874.        * make this number adaptable.
  875.        */
  876.       xpos += menu->menu.Width;
  877.       if (xpos > swidth) return(NULL);
  878.       xpos += 8;
  879.    }
  880.    return(TRUE);
  881. }
  882.  
  883. /***********************************************************************************
  884.  * Procedure: v_free_menus
  885.  * Synopsis:  v_free_menus(Menu);
  886.  * Purpose:   Return any storage allocated for a given Menu structure.
  887.  ***********************************************************************************/
  888. void v_free_menus(struct Menu *menus)
  889. {
  890.    struct XMenu *menu, *nextmenu;
  891.    struct XItem *item, *nextitem;
  892.  
  893.       for (menu = (struct XMenu *)menus; menu; menu = nextmenu) {
  894.          nextmenu = (struct XMenu *)menu->menu.NextMenu;
  895.          for (item = (struct XItem *)menu->menu.FirstItem; item; item = nextitem) {
  896.             nextitem = (struct XItem *)item->item.NextItem;
  897.             free(item);
  898.          }
  899.          free(menu);
  900.       }
  901. }
  902.  
  903. /***********************************************************************************
  904.  * Procedure: text_width
  905.  * Synopsis:  len = text_width(str)
  906.  * Purpose:   Return the rendered width of a given string
  907.  ***********************************************************************************/
  908. int text_width(char *str)
  909. {
  910.    struct IntuiText itext;
  911.  
  912.    itext.FrontPen  = 1;
  913.    itext.BackPen   = 0;
  914.    itext.DrawMode  = JAM1;
  915.    itext.LeftEdge  = 0;
  916.    itext.TopEdge   = 1;
  917.    itext.ITextFont = &TOPAZ80;    // replace with actual font
  918.    itext.NextText  = NULL;
  919.    itext.IText     = str;
  920.  
  921.    return(IntuiTextLength(&itext));
  922. }